# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import os
import json
import time
import re

from django.shortcuts import render, reverse, redirect
from django.contrib.auth import authenticate, login, logout, get_user

# from django.contrib.auth.models import User, Group, Permission
from .models import SmAdminUser, SmadminRole, SmadminPermission, SmadminRolePermission

from django.contrib.auth.decorators import login_required, permission_required

from django.http import HttpResponse, HttpResponseRedirect, Http404

from jqgrid import JqGrid

import logging

# Get an instance of a logger
logger = logging.getLogger("smAdmin")

from . import models_test


@permission_required('polls.can_vote')
def test(request):
	context = {}
	models_test.getAccount()

	# return render(request, "smAdmin/base.html", context=context)
	return HttpResponse("ok", content_type="text/plain")


def login_view(request):
	context = {}
	return render(request, "smAdmin/login.html", context=context)


def api_login(request):
	username = request.POST.get("username")
	password = request.POST.get("password")

	aUser = SmAdminUser.objects.get(username=username)
	if not aUser:
		logger.info("登录：用户名[%s]不存在" % (username,))
	else:
		logger.info("登录：用户名[%s]在数据库中的密码[%s]" % (username, aUser.password))

	# aUser.set_password(password)
	# aUser.save()

	user = authenticate(username=username, password=password)
	if user is not None:
		if user.is_active:
			login(request, user)
			# Redirect to a success page.
			# return HttpResponseRedirect(reverse('smAdmin:main'))
			resp_data = {
				"c": 0,
				"m": u"登录成功！"
			}
			# 设置session的过期时间为 30 分钟
			request.session.set_expiry(30 * 60)
			return HttpResponse(json.dumps(resp_data), content_type="application/json")
		else:
			# Return a 'disabled account' error message
			resp_data = {
				"c": 5,
				"m": u"账号已禁用！"
			}
			return HttpResponse(json.dumps(resp_data), content_type="application/json")
	else:
		# Return an 'invalid login' error message.
		resp_data = {
			"c": 4,
			"m": u"账号或者密码错误！"
		}
		return HttpResponse(json.dumps(resp_data), content_type="application/json")


@login_required(login_url="/smAdmin/login")
def logout_view(request):
	"""
	退出
	:param request:
	:return:
	"""
	logout(request)
	return redirect(reverse('smAdmin:login'))


@login_required(login_url="/smAdmin/login")
@permission_required('submenu.my_profile.profile')
def profile_view(request):
	"""
	用户信息
	:param request:
	:return:
	"""

	role_name = u"管理员"
	user = get_user(request)

	# 用户信息
	user_info = []
	for field in user._meta.fields:
		field_name = field.name
		field_value = getattr(user, field.name)
		if field_value is None:
			field_value = ""
		if field_name in ("password", "is_superuser"):
			continue

		logger.info(u"%s,%s,%s" % (field.verbose_name, field_name, field_value))
		if field_name == "role":  # 角色名称
			field_value = field_value.name

		# 标签
		label = field.verbose_name
		if field.choices:
			for item in field.choices:
				if field_value == item[0]:
					field_value = item[1]
					break

		user_info.append({"name": field_name, "label": label, "value": field_value})

	context = {
		"role_name": role_name,
		"user_info": user_info,

	}
	return render(request, "smAdmin/user/profile.html", context=context)


@login_required(login_url="/smAdmin/login")
@permission_required('submenu.my_profile.change_pwd')
def change_pwd_view(request):
	"""
	修改密码
	:param request:
	:return:
	"""
	user = get_user(request)
	context = {
		"username": user.username,
	}
	return render(request, "smAdmin/user/change_pwd.html", context=context)


# 密码验证的正则表达式
CHECK_PWD_RE = "(?!^\\d+$)(?!^[a-zA-Z]+$)(?!^[_#@]+$).{8,16}"
CHECK_PWD_RE_TIP_MSG = u"密码必须包含数字和字母，8到16位"


@login_required(login_url="/smAdmin/login")
@permission_required('submenu.my_profile.change_pwd')
def api_change_pwd(request):
	"""
	修改密码接口
	:param request:
	:return:
	"""
	user = get_user(request)
	old_password = request.POST.get("old_password")
	new_password = request.POST.get("new_password")
	re_new_password = request.POST.get("re_new_password")

	result = {"result": 0, "reason": u"修改成功"}
	if not old_password:
		result = {"result": 2, "reason": u"请输入原密码"}
	elif not new_password:
		result = {"result": 2, "reason": u"请输入新密码"}
	elif new_password != re_new_password:
		result = {"result": 2, "reason": u"两次输入的密码不相同"}
	else:
		# 检查用户密码
		p = re.compile(CHECK_PWD_RE)
		if not p.match(new_password):
			result = {"result": 2, "reason": CHECK_PWD_RE_TIP_MSG}

	if result["result"] != 0:
		return HttpResponse(json.dumps(result), content_type="application/json")

	user = authenticate(username=user.username, password=old_password)
	if user is None:
		resp_data = {
			"c": 4,
			"m": u"原密码错误！"
		}
		return HttpResponse(json.dumps(resp_data), content_type="application/json")

	user.set_password(new_password)
	login_url = reverse('smAdmin:login')
	resp_data = {
		"c": 0,
		"login_url": login_url,
		"m": u"修改成功！"
	}
	# logout(request)
	return HttpResponse(json.dumps(resp_data), content_type="application/json")


# @permission_required('smAdmin.can_vote', login_url='/smAdmin/login')
@login_required(login_url="/smAdmin/login")
def main_view(request):
	"""
	管理后台主框架
	:param request:
	:return:
	"""
	user = get_user(request)
	rolePermissions = SmadminRolePermission.objects.filter(role=user.role).all()

	menus = []
	menuData = {"menus": menus}
	menuPermissions = SmadminPermission.objects.filter(parent_id=0).all()
	for menu in menuPermissions:
		menu_is_check = checkRolePermissionById(rolePermissions, menu.id)
		if not menu_is_check:
			continue
		subMenus = []
		subMenuPermissions = SmadminPermission.objects.filter(parent_id=menu.id).all()
		for sub_menu in subMenuPermissions:
			sub_menu_is_check = checkRolePermissionById(rolePermissions, sub_menu.id)
			if sub_menu_is_check:
				subMenus.append({"id": sub_menu.id, "title": sub_menu.title, "url": sub_menu.url, "sort": sub_menu.sort})
		subMenus.sort(lambda a, b: 1 if a["sort"] > b["sort"] else -1)
		menus.append({"id": menu.id, "title": menu.title, "url": menu.url, "sort": menu.sort, "subMenus": subMenus, "icon_class": menu.icon_class})

	menus.sort(lambda a, b: 1 if a["sort"] > b["sort"] else -1)

	logger.info(json.dumps(menuData, indent=2))

	context = {
		"username": user.username,
		"menuData": menuData,
	}
	return render(request, "smAdmin/main.html", context=context)


@login_required(login_url="/smAdmin/login")
@permission_required('menu.dashboard')
def dashboard_view(request):
	return render(request, "smAdmin/dashboard/dashboard.html")


# ------------- 用户 ------------------
'''
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `password` varchar(128) COLLATE utf8_bin NOT NULL,
  `last_login` datetime(6) DEFAULT NULL,
  `is_superuser` tinyint(1) NOT NULL,
  `username` varchar(150) COLLATE utf8_bin NOT NULL,
  `first_name` varchar(30) COLLATE utf8_bin NOT NULL,
  `last_name` varchar(30) COLLATE utf8_bin NOT NULL,
  `email` varchar(254) COLLATE utf8_bin NOT NULL,
  `is_staff` tinyint(1) NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  `date_joined` datetime(6) NOT NULL,
'''


class UserGrid(JqGrid):
	model = SmAdminUser  # could also be a queryset
	# fields = ['myac', 'id', 'password', 'last_login', 'is_superuser', 'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'date_joined']  # optional
	fields = ['id', 'username', 'last_name', 'first_name', 'role_id', 'email', 'is_staff', 'is_active', 'myac']  # optional
	url = '/smAdmin/setting/user_list'
	editurl = '/smAdmin/setting/user_edit'
	caption = u'用户'  # optional
	colmodel_overrides = {  # optional
		'id': {'hidden': True, 'width': 60},
		'username': {'editable': True, 'width': 100},
		'last_name': {'editable': True, 'width': 80},
		'first_name': {'editable': True, 'width': 80},
		'role_id': {'editable': True, 'width': 60},
		'is_superuser': {
			"editable": True,
			"edittype": 'select',
			"editoptions": {
				"value": "0:否;1:是"
			},
			'width': 60
		},
		'email': {'editable': True, 'width': 100},
		'is_staff': {
			"editable": True,
			"edittype": 'select',
			"editoptions": {
				"value": "0:离职;1:在职"
			},
			'width': 60
		},
		'is_active': {
			"editable": True,
			"edittype": 'select',
			"editoptions": {
				"value": "0:禁用;1:正常"
			},
			'width': 60
		},
		'date_joined': {'editable': False, 'width': 100, "datefmt": "yyyy/mm/dd"},
		'last_login': {'editable': False, 'width': 100},
		'myac': {
			"label": u"操作",
			'editable': False,
			"width": 80,
			"fixed": True,
			"sortable": False,
			"resize": False,
			"formatter": 'actions',
			"formatoptions": {"keys": True, "delbutton": False, }
		}
	}
	pass


@login_required(login_url="/smAdmin/login")
@permission_required('submen.perm_setting.user')
def setting_user(request):
	"""
	后台用户管理
	:param request:
	:return:
	"""
	grid = UserGrid()

	roles = []
	role_set = SmadminRole.objects.all()
	for role in role_set:
		roles.append({"id": role.id, "name": role.name})

	context = {
		"grid_config": grid.get_config(),
		"roles": json.dumps(roles)
	}

	return render(request, "smAdmin/setting/user.html", context=context)


@login_required(login_url="/smAdmin/login")
@permission_required('perm_setting.user.list')
def setting_user_list(request):
	""" 查询用户列表
	:param request:
	:return:
	"""
	grid = UserGrid()
	return HttpResponse(grid.get_json(request), content_type="application/json")


@login_required(login_url="/smAdmin/login")
@permission_required(['perm_setting.user.add', 'perm_setting.user.edit', 'perm_setting.user.del'])
def setting_user_edit(request):
	""" 编辑，添加，删除
	:param request:
	:return:
	"""
	oper = request.POST.get('oper')
	id = request.POST.get('id')

	user = get_user(request)

	grid = UserGrid()
	if oper == 'edit':
		if not user.has_perm("perm_setting.user.edit"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if not id:
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.edit_object(request, id):
			return HttpResponse(content_type="application/x-javascript", status=200)
	elif oper == 'add':
		if not user.has_perm("perm_setting.user.add"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.add_object(request):
			return HttpResponse(content_type="application/x-javascript", status=200)
	elif oper == 'del':
		if not user.has_perm("perm_setting.user.del"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if not id:
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.delete_object(request, id):
			return HttpResponse(content_type="application/x-javascript", status=200)

	return HttpResponse(content_type="application/x-javascript", status=406)


# -------------用户组------------------
class UserGroupGrid(JqGrid):
	model = SmadminRole  # could also be a queryset
	fields = ['id', 'name', 'myac', ]  # optional
	url = '/smAdmin/setting/group_list'
	editurl = '/smAdmin/setting/group_edit'
	caption = u'用户组'  # optional
	colmodel_overrides = {  # optional
		'id': {'key': True, 'width': 20, "hidden": True},
		'name': {'width': 100},
		'myac': {
			"name": 'myac',
			"index": 'myac',
			"label": u"操作",
			'editable': False,
			"width": 100,
			"fixed": True,
			"sortable": False,
			"resize": False,
			"formatter": 'actions',
			"formatoptions": {"keys": True, "delbutton": False, }
		}
	}


@login_required(login_url="/smAdmin/login")
@permission_required(['submen.perm_setting.group', ])
def setting_group(request):
	"""
	后台用户组管理
	:param request:
	:return:
	"""
	grid = UserGroupGrid()
	context = {
		"grid_config": grid.get_config(),
	}
	return render(request, "smAdmin/setting/group.html", context=context)


@login_required(login_url="/smAdmin/login")
@permission_required(['perm_setting.group.list', ])
def setting_group_list(request):
	# handles pagination, sorting and searching
	grid = UserGroupGrid()
	return HttpResponse(grid.get_json(request), content_type="application/json")


@login_required(login_url="/smAdmin/login")
@permission_required(['perm_setting.group.add', 'perm_setting.group.edit', 'perm_setting.group.del'])
def setting_group_edit(request):
	oper = request.POST.get('oper')
	id = request.POST.get('id')

	grid = UserGroupGrid()
	user = get_user(request)
	if oper == 'edit':
		if not user.has_perm("perm_setting.group.edit"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if not id:
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.edit_object(request, id):
			return HttpResponse(content_type="application/x-javascript", status=200)
	elif oper == 'add':
		if not user.has_perm("perm_setting.group.add"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.add_object(request):
			return HttpResponse(content_type="application/x-javascript", status=200)
		logger.error("添加角色失败：提交参数[%s]" % (request.POST,))
	elif oper == 'del':
		if not user.has_perm("perm_setting.group.del"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if not id:
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.delete_object(request, id):
			return HttpResponse(content_type="application/x-javascript", status=200)

	return HttpResponse(content_type="application/x-javascript", status=406)


def checkRolePermissionById(rolePermissions, permission_id):
	for p in rolePermissions:
		if p.permission_id == permission_id and p.checked != 0:
			return True
	return False


def hasPermLine(rolePermissions, permission_id):
	for p in rolePermissions:
		if p.permission_id == permission_id:
			return True
	return False


@login_required(login_url="/smAdmin/login")
@permission_required(['perm_setting.group.set_perm', ])
def group_set_permission_view(request):
	# request.POST
	role_id = request.GET.get("role_id")
	if not role_id:
		context = {"reason": "参数role_id为空"}
		return render(request, 'smAdmin/setting/set_permissions_error.html', context=context)

	roleObj = SmadminRole.objects.get(id=role_id)
	if not roleObj:
		context = {"reason": "用户组[%s]不存在" % (role_id,)}
		return render(request, 'smAdmin/setting/set_permissions_error.html', context=context)

	# 查询所有权限，把该角色目前没有的权限全部添加到关联表中，设置check=0
	basePermissions = SmadminPermission.objects.all()  # 所有权限
	logger.info("权限表中的权限总数为[%s]" % (len(basePermissions),))
	rolePermissions = SmadminRolePermission.objects.filter(role=roleObj).all()
	logger.info("角色[%s][%s]权限关系表中的记录数位[%s]" % (roleObj.name, roleObj.id, len(rolePermissions)))
	querysetlist = []
	for basePerm in basePermissions:
		if not hasPermLine(rolePermissions, basePerm.id):
			rolePerm = SmadminRolePermission(role=roleObj, permission=basePerm, checked=0)
			querysetlist.append(rolePerm)
			logger.info("给角色[%s][%s]添加新权限[%s][%s]，设置checked[0]" % (roleObj.name, roleObj.id, basePerm.codename, basePerm.id))
	if querysetlist:
		SmadminRolePermission.objects.bulk_create(querysetlist)

	menus = []
	permissionData = {"menus": menus}
	menuPermissions = SmadminPermission.objects.filter(parent_id=0).all()
	for menu in menuPermissions:
		subMenus = []
		subMenuPermissions = SmadminPermission.objects.filter(parent_id=menu.id).all()
		totalRowSpan = 0
		for sub_menu in subMenuPermissions:
			permissions = []
			elementPermissions = SmadminPermission.objects.filter(parent_id=sub_menu.id).all()
			for perm in elementPermissions:
				permissions.append({
					"id": perm.id,
					"title": perm.title,
					"checked": checkRolePermissionById(rolePermissions, perm.id)
				})

			rowSpan = len(permissions) + 1
			sub_menu_is_check = checkRolePermissionById(rolePermissions, sub_menu.id)
			subMenus.append({"id": sub_menu.id, "title": sub_menu.title, "rowspan": rowSpan, "checked": sub_menu_is_check, "permissions": permissions})
			totalRowSpan += rowSpan

		totalRowSpan += 1
		menu_is_check = checkRolePermissionById(rolePermissions, menu.id)
		menus.append({"id": menu.id, "title": menu.title, "subMenus": subMenus, "rowspan": totalRowSpan, "checked": menu_is_check})

	context = {
		"role_id": role_id,
		"permissionData": permissionData
	}
	# logger.info(json.dumps(permissionData, indent=2))
	return render(request, 'smAdmin/setting/set_permissions.html', context=context)


@login_required(login_url="/smAdmin/login")
@permission_required(['perm_setting.group.set_perm', ])
def group_set_permissions(request):
	permission_checked_list = []
	for k, v in request.POST.items():
		if k.startswith("check_"):
			a_id = k[len('check_'):]
			if v == "on":
				permission_checked_list.append(int(a_id))

	def isCheck(permission_list, permission_id):
		for p_id in permission_list:  # 已经选择的权限Id列表
			if p_id == permission_id:
				return True
		return False

	role_id = request.POST.get("role_id")
	logger.info("=====设置角色[%s]的权限=====" % (role_id,))
	rolePermissions = SmadminRolePermission.objects.filter(role_id=role_id).all()
	logger.info("权限数量：%s" % (len(rolePermissions)))
	for p in rolePermissions:
		if isCheck(permission_checked_list, p.permission_id):
			p.checked = 1
		else:
			p.checked = 0
		p.save()

	ret_data = {"result": 0, "reason": "设置成功"}
	return HttpResponse(json.dumps(ret_data), content_type="application/json")


# -------------权限------------------
class PermissionGrid(JqGrid):
	model = SmadminPermission  # could also be a queryset
	fields = ['id', 'codename', 'title', 'type', 'parent_id', 'sort', 'url', 'icon_class']
	url = '/smAdmin/setting/permission_list'
	editurl = '/smAdmin/setting/permission_edit'
	caption = u'权限'  # optional
	colmodel_overrides = {  # optional
		'id': {'editable': True, "editrules": {"edithidden": True}, 'hidden': False, 'width': 60},
		'codename': {'editable': True, 'width': 100},
		'title': {'editable': True, 'width': 100},
		'type': {
			"editable": True,
			"edittype": 'select',
			"editoptions": {"value": "menu:菜单;submenu:二级菜单;element:元素"},
			'width': 60
		},
		'url': {'editable': True, 'width': 100},
		'parent_id': {'editable': True, 'width': 60},
		'sort': {'editable': True, 'width': 60},
		'icon_class': {
			"editable": True,
			"edittype": 'text',
			"editoptions": {"size": "20", "maxlength": "32"},

			'width': 100
		},
	}
	extra_config = {
		'rownumbers': False,
	}


@login_required(login_url="/smAdmin/login")
@permission_required(['submenu.perm_setting.permission', ])
def setting_permission(request):
	"""
	后台用户组管理
	:param request:
	:return:
	"""
	grid = PermissionGrid()
	grid_config_info = grid.get_config()
	context = {
		"grid_config": grid_config_info,
	}
	return render(request, "smAdmin/setting/permissions.html", context=context)


@login_required(login_url="/smAdmin/login")
@permission_required(['perm_setting.permission.list', ])
def setting_permission_list(request):
	# handles pagination, sorting and searching
	grid = PermissionGrid()
	return HttpResponse(grid.get_json(request), content_type="application/json")


@login_required(login_url="/smAdmin/login")
@permission_required(['perm_setting.permission.add', 'perm_setting.permission.edit', 'perm_setting.permission.del'])
def setting_permission_edit(request):
	"""
	编辑
	:param request:
	:return:

	name	"hello"
	content_type	"1"
	codename	"change_logentry"
	oper	"edit"
	id	"2"
	"""
	grid = PermissionGrid()

	oper = request.POST.get('oper')
	id = request.POST.get('id')
	user = get_user(request)

	if oper == 'edit':
		if not user.has_perm("perm_setting.permission.edit"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if not id:
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.edit_object(request, id):
			return HttpResponse(content_type="application/x-javascript", status=200)
	elif oper == 'add':
		if not user.has_perm("perm_setting.permission.add"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.add_object(request):
			return HttpResponse(content_type="application/x-javascript", status=200)
	elif oper == 'del':
		if not user.has_perm("perm_setting.permission.del"):
			return HttpResponse(content_type="application/x-javascript", status=420)
		if not id:
			return HttpResponse(content_type="application/x-javascript", status=420)
		if grid.delete_object(request, id):
			return HttpResponse(content_type="application/x-javascript", status=200)

	return HttpResponse(content_type="application/x-javascript", status=406)


from django.views.decorators.csrf import csrf_exempt

@login_required(login_url="/smAdmin/login")
@csrf_exempt  # 不校验CSRF
def FileUpload(request):
	"""文件上传接口
	"""
	image = request.FILES.get('file')
	if not image:
		ret = {"result": 1, "reason": u"参数错误"}
		return HttpResponse(json.dumps(ret), content_type="application/json")

	if request.method == 'POST':
		image_filename = '%s_%s' % (int(time.time()), str(image))  # 名字独特性使用时间戳添加名字
		logger.info("将要保存文件名为:%s" % (image_filename,))

		media_path = "smAdmin/static/smAdmin/media/upload"
		logger.info("保存文件名全路径:%s" % (os.path.abspath(media_path),))

		if not os.path.exists(media_path) or not os.path.isdir(media_path):
			os.makedirs(media_path)

		try:
			save_path = "%s/%s" % (media_path, image_filename,)
			fp = open(save_path, 'wb')
			s = image.read()
			fp.write(s)
			fp.close()

			img_url = "/static/smAdmin/media/upload/%s" % (image_filename,)
			ret = {
				"result": 0,
				"reason": u"上传成功",
				"img_url": img_url
			}
		except:
			ret = {"result": -1, "reason": u"上传失败"}

		return HttpResponse(json.dumps(ret), content_type="application/json")
	else:
		# 跳转到错误页面
		# ret = copy.deepcopy(config.ERROR_CODE_INFO[""])
		raise Http404("页面不存在")
